{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 神经网络迷你项目"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ----------\n",
    "# \n",
    "# In this exercise, you will add in code that decides whether a perceptron will fire based\n",
    "# on the threshold. Your code will go in lines 32 and 34. \n",
    "#\n",
    "# ----------\n",
    "import numpy as np\n",
    "\n",
    "class Perceptron:\n",
    "    \"\"\"\n",
    "    This class models an artificial neuron with step activation function.\n",
    "    \"\"\"\n",
    "    def __init__(self, weights = np.array([1]), threshold = 0):\n",
    "        \"\"\"\n",
    "        Initialize weights and threshold based on input arguments. Note that no\n",
    "        type-checking is being performed here for simplicity.\n",
    "        \"\"\"\n",
    "        self.weights = weights\n",
    "        self.threshold = threshold\n",
    "    \n",
    "    def activate(self,inputs):\n",
    "        \"\"\"\n",
    "        Takes in @param inputs, a list of numbers equal to length of weights.\n",
    "        @return the output of a threshold perceptron with given inputs based on\n",
    "        perceptron weights and threshold.\n",
    "        \"\"\" \n",
    "\n",
    "        # The strength with which the perceptron fires.\n",
    "        strength = np.dot(self.weights, inputs)\n",
    "        # TODO: return 0 or 1 based on the threshold\n",
    "        if strength <= self.threshold :\n",
    "            self.result = # TODO\n",
    "        else:\n",
    "            self.result = # TODO    \n",
    "        return self.result\n",
    "\n",
    "\n",
    "def test():\n",
    "    \"\"\"\n",
    "    A few tests to make sure that the perceptron class performs as expected.\n",
    "    Nothing should show up in the output if all the assertions pass.\n",
    "    \"\"\"\n",
    "    p1 = Perceptron(np.array([1, 2]), 0.)\n",
    "    assert p1.activate(np.array([ 1,-1])) == 0 # < threshold --> 0\n",
    "    assert p1.activate(np.array([-1, 1])) == 1 # > threshold --> 1\n",
    "    assert p1.activate(np.array([ 2,-1])) == 0 # on threshold --> 0\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    test()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ----------\n",
    "#\n",
    "# In this exercise, you will update the perceptron class so that it can update\n",
    "# its weights.\n",
    "#\n",
    "# Finish writing the update() method so that it updates the weights according\n",
    "# to the perceptron update rule. Updates should be performed online, revising\n",
    "# the weights after each data point.\n",
    "#\n",
    "# YOUR CODE WILL GO IN LINES 51 AND 59.\n",
    "# ----------\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "class Perceptron:\n",
    "    \"\"\"\n",
    "    This class models an artificial neuron with step activation function.\n",
    "    \"\"\"\n",
    "    def __init__(self, weights = np.array([1]), threshold = 0):\n",
    "        \"\"\"\n",
    "        Initialize weights and threshold based on input arguments. Note that no\n",
    "        type-checking is being performed here for simplicity.\n",
    "        \"\"\"\n",
    "        self.weights = weights.astype(float) \n",
    "        self.threshold = threshold\n",
    "\n",
    "\n",
    "    def activate(self, values):\n",
    "        \"\"\"\n",
    "        Takes in @param values, a list of numbers equal to length of weights.\n",
    "        @return the output of a threshold perceptron with given inputs based on\n",
    "        perceptron weights and threshold.\n",
    "        \"\"\"\n",
    "        # First calculate the strength with which the perceptron fires\n",
    "        strength = np.dot(values,self.weights)\n",
    "        # Then return 0 or 1 depending on strength compared to threshold  \n",
    "        return int(strength > self.threshold)\n",
    "\n",
    "\n",
    "    def update(self, values, train, eta=.1):\n",
    "        \"\"\"\n",
    "        Takes in a 2D array @param values consisting of a LIST of inputs and a\n",
    "        1D array @param train, consisting of a corresponding list of expected\n",
    "        outputs. Updates internal weights according to the perceptron training\n",
    "        rule using these values and an optional learning rate, @param eta.\n",
    "        \"\"\"\n",
    "\n",
    "        # For each data point:\n",
    "        for data_point in xrange(len(values)):\n",
    "            # TODO: Obtain the neuron's prediction for the data_point --> values[data_point]\n",
    "            prediction = self.activate(# TODO)\n",
    "            # Get the prediction accuracy calculated as (expected value - predicted value)\n",
    "            # expected value = train[data_point], predicted value = prediction\n",
    "            error = train[data_point] - prediction\n",
    "            # TODO: update self.weights based on the multiplication of:\n",
    "            # - prediction accuracy(error)\n",
    "            # - learning rate(eta)\n",
    "            # - input value(values[data_point])\n",
    "            weight_update = # TODO\n",
    "            self.weights += weight_update\n",
    "\n",
    "def test():\n",
    "    \"\"\"\n",
    "    A few tests to make sure that the perceptron class performs as expected.\n",
    "    Nothing should show up in the output if all the assertions pass.\n",
    "    \"\"\"\n",
    "    def sum_almost_equal(array1, array2, tol = 1e-6):\n",
    "        return sum(abs(array1 - array2)) < tol\n",
    "\n",
    "    p1 = Perceptron(np.array([1,1,1]),0)\n",
    "    p1.update(np.array([[2,0,-3]]), np.array([1]))\n",
    "    assert sum_almost_equal(p1.weights, np.array([1.2, 1, 0.7]))\n",
    "\n",
    "    p2 = Perceptron(np.array([1,2,3]),0)\n",
    "    p2.update(np.array([[3,2,1],[4,0,-1]]),np.array([0,0]))\n",
    "    assert sum_almost_equal(p2.weights, np.array([0.7, 1.8, 2.9]))\n",
    "\n",
    "    p3 = Perceptron(np.array([3,0,2]),0)\n",
    "    p3.update(np.array([[2,-2,4],[-1,-3,2],[0,2,1]]),np.array([0,1,0]))\n",
    "    assert sum_almost_equal(p3.weights, np.array([2.7, -0.3, 1.7]))\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    test()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ----------\n",
    "#\n",
    "# In this exercise, you will create a network of perceptrons that can represent\n",
    "# the XOR function, using a network structure like those shown in the previous\n",
    "# quizzes.\n",
    "#\n",
    "# You will need to do two things:\n",
    "# First, create a network of perceptrons with the correct weights\n",
    "# Second, define a procedure EvalNetwork() which takes in a list of inputs and\n",
    "# outputs the value of this network.\n",
    "#\n",
    "# ----------\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "class Perceptron:\n",
    "    \"\"\"\n",
    "    This class models an artificial neuron with step activation function.\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, weights = np.array([1]), threshold = 0):\n",
    "        \"\"\"\n",
    "        Initialize weights and threshold based on input arguments. Note that no\n",
    "        type-checking is being performed here for simplicity.\n",
    "        \"\"\"\n",
    "        self.weights = weights\n",
    "        self.threshold = threshold\n",
    "\n",
    "\n",
    "    def activate(self, values):\n",
    "        \"\"\"\n",
    "        Takes in @param values, a list of numbers equal to length of weights.\n",
    "        @return the output of a threshold perceptron with given inputs based on\n",
    "        perceptron weights and threshold.\n",
    "        \"\"\"\n",
    "               \n",
    "        # First calculate the strength with which the perceptron fires\n",
    "        strength = np.dot(values,self.weights)\n",
    "        \n",
    "        # Then return 0 or 1 depending on strength compared to threshold  \n",
    "        return int(strength > self.threshold)\n",
    "\n",
    "            \n",
    "# Part 1: Set up the perceptron network\n",
    "Network = [\n",
    "    # input layer, declare input layer perceptrons here\n",
    "    [ ... ], \\\n",
    "    # output node, declare output layer perceptron here\n",
    "    [ ... ]\n",
    "]\n",
    "\n",
    "# Part 2: Define a procedure to compute the output of the network, given inputs\n",
    "def EvalNetwork(inputValues, Network):\n",
    "    \"\"\"\n",
    "    Takes in @param inputValues, a list of input values, and @param Network\n",
    "    that specifies a perceptron network. @return the output of the Network for\n",
    "    the given set of inputs.\n",
    "    \"\"\"\n",
    "    \n",
    "    # YOUR CODE HERE\n",
    "\n",
    "    # Be sure your output value is a single number\n",
    "    return OutputValue\n",
    "\n",
    "\n",
    "def test():\n",
    "    \"\"\"\n",
    "    A few tests to make sure that the perceptron class performs as expected.\n",
    "    \"\"\"\n",
    "    print \"0 XOR 0 = 0?:\", EvalNetwork(np.array([0,0]), Network)\n",
    "    print \"0 XOR 1 = 1?:\", EvalNetwork(np.array([0,1]), Network)\n",
    "    print \"1 XOR 0 = 1?:\", EvalNetwork(np.array([1,0]), Network)\n",
    "    print \"1 XOR 1 = 0?:\", EvalNetwork(np.array([1,1]), Network)\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    test()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ----------\n",
    "# \n",
    "# Python Neural Networks code originally by Szabo Roland and used with\n",
    "# permission\n",
    "#\n",
    "# Modifications, comments, and exercise breakdowns by Mitchell Owen,\n",
    "# (c) Udacity\n",
    "#\n",
    "# Retrieved originally from http://rolisz.ro/2013/04/18/neural-networks-in-python/\n",
    "#\n",
    "#\n",
    "# Neural Network Sandbox\n",
    "#\n",
    "# Define an activation function activate(), which takes in a number and\n",
    "# returns a number.\n",
    "# Using test run you can see the performance of a neural network running with\n",
    "# that activation function, where the inputs are 8x8 images of digits (0-9) and\n",
    "# the outputs are digit predictions made by the network.\n",
    "#\n",
    "# ----------\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "def activate(strength):\n",
    "    # Try out different functions here. Input strength will be a number, with\n",
    "    # another number as output.\n",
    "    return np.power(strength,2)\n",
    "    \n",
    "def activation_derivative(activate, strength):\n",
    "    #numerically approximate\n",
    "    return (activate(strength+1e-5)-activate(strength-1e-5))/(2e-5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ----------\n",
    "# \n",
    "# As with the previous perceptron exercises, you will complete some of the core\n",
    "# methods of a sigmoid unit class.\n",
    "#\n",
    "# There are two functions for you to finish:\n",
    "# First, in activate(), write the sigmoid activation function.\n",
    "# Second, in update(), write the gradient descent update rule. Updates should be\n",
    "#   performed online, revising the weights after each data point.\n",
    "# \n",
    "# ----------\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "class Sigmoid:\n",
    "    \"\"\"\n",
    "    This class models an artificial neuron with sigmoid activation function.\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, weights = np.array([1])):\n",
    "        \"\"\"\n",
    "        Initialize weights based on input arguments. Note that no type-checking\n",
    "        is being performed here for simplicity of code.\n",
    "        \"\"\"\n",
    "        self.weights = weights\n",
    "\n",
    "        # NOTE: You do not need to worry about these two attribues for this\n",
    "        # programming quiz, but these will be useful for if you want to create\n",
    "        # a network out of these sigmoid units!\n",
    "        self.last_input = 0 # strength of last input\n",
    "        self.delta      = 0 # error signal\n",
    "\n",
    "    def activate(self, values):\n",
    "        \"\"\"\n",
    "        Takes in @param values, a list of numbers equal to length of weights.\n",
    "        @return the output of a sigmoid unit with given inputs based on unit\n",
    "        weights.\n",
    "        \"\"\"\n",
    "        \n",
    "        # YOUR CODE HERE\n",
    "        \n",
    "        # First calculate the strength of the input signal.\n",
    "        strength = np.dot(values, self.weights)\n",
    "        self.last_input = strength\n",
    "        \n",
    "        # TODO: Modify strength using the sigmoid activation function and\n",
    "        # return as output signal.\n",
    "        # HINT: You may want to create a helper function to compute the\n",
    "        #   logistic function since you will need it for the update function.\n",
    "        \n",
    "        return result\n",
    "    \n",
    "    def update(self, values, train, eta=.1):\n",
    "        \"\"\"\n",
    "        Takes in a 2D array @param values consisting of a LIST of inputs and a\n",
    "        1D array @param train, consisting of a corresponding list of expected\n",
    "        outputs. Updates internal weights according to gradient descent using\n",
    "        these values and an optional learning rate, @param eta.\n",
    "        \"\"\"\n",
    "\n",
    "        # TODO: for each data point...\n",
    "        for X, y_true in zip(values, train):\n",
    "            # obtain the output signal for that point\n",
    "            y_pred = self.activate(X)\n",
    "\n",
    "            # YOUR CODE HERE\n",
    "\n",
    "            # TODO: compute derivative of logistic function at input strength\n",
    "            # Recall: d/dx logistic(x) = logistic(x)*(1-logistic(x))\n",
    "\n",
    "            # TODO: update self.weights based on learning rate, signal accuracy,\n",
    "            # function slope (derivative) and input value\n",
    "            \n",
    "\n",
    "def test():\n",
    "    \"\"\"\n",
    "    A few tests to make sure that the perceptron class performs as expected.\n",
    "    Nothing should show up in the output if all the assertions pass.\n",
    "    \"\"\"\n",
    "    def sum_almost_equal(array1, array2, tol = 1e-5):\n",
    "        return sum(abs(array1 - array2)) < tol\n",
    "\n",
    "    u1 = Sigmoid(weights=[3,-2,1])\n",
    "    assert abs(u1.activate(np.array([1,2,3])) - 0.880797) < 1e-5\n",
    "    \n",
    "    u1.update(np.array([[1,2,3]]),np.array([0]))\n",
    "    assert sum_almost_equal(u1.weights, np.array([2.990752, -2.018496, 0.972257]))\n",
    "\n",
    "    u2 = Sigmoid(weights=[0,3,-1])\n",
    "    u2.update(np.array([[-3,-1,2],[2,1,2]]),np.array([1,0]))\n",
    "    assert sum_almost_equal(u2.weights, np.array([-0.030739, 2.984961, -1.027437]))\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    test()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 贝叶斯"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#------------------------------------------------------------------\n",
    "\n",
    "#\n",
    "#   Bayes Optimal Classifier\n",
    "#\n",
    "#   In this quiz we will compute the optimal label for a second missing word in a row\n",
    "#   based on the possible words that could be in the first blank\n",
    "#\n",
    "#   Finish the procedurce, LaterWords(), below\n",
    "#\n",
    "#   You may want to import your code from the previous programming exercise!\n",
    "#\n",
    "\n",
    "sample_memo = '''\n",
    "Milt, we're gonna need to go ahead and move you downstairs into storage B. We have some new people coming in, and we need all the space we can get. So if you could just go ahead and pack up your stuff and move it down there, that would be terrific, OK?\n",
    "Oh, and remember: next Friday... is Hawaiian shirt day. So, you know, if you want to, go ahead and wear a Hawaiian shirt and jeans.\n",
    "Oh, oh, and I almost forgot. Ahh, I'm also gonna need you to go ahead and come in on Sunday, too...\n",
    "Hello Peter, whats happening? Ummm, I'm gonna need you to go ahead and come in tomorrow. So if you could be here around 9 that would be great, mmmk... oh oh! and I almost forgot ahh, I'm also gonna need you to go ahead and come in on Sunday too, kay. We ahh lost some people this week and ah, we sorta need to play catch up.\n",
    "'''\n",
    "\n",
    "corrupted_memo = '''\n",
    "Yeah, I'm gonna --- you to go ahead --- --- complain about this. Oh, and if you could --- --- and sit at the kids' table, that'd be --- \n",
    "'''\n",
    "\n",
    "data_list = sample_memo.strip().split()\n",
    "\n",
    "words_to_guess = [\"ahead\",\"could\"]\n",
    "\n",
    "def LaterWords(sample,word,distance):\n",
    "    '''@param sample: a sample of text to draw from\n",
    "    @param word: a word occuring before a corrupted sequence\n",
    "    @param distance: how many words later to estimate (i.e. 1 for the next word, 2 for the word after that)\n",
    "    @returns: a single word which is the most likely possibility\n",
    "    '''\n",
    "    \n",
    "    # TODO: Given a word, collect the relative probabilities of possible following words\n",
    "    # from @sample. You may want to import your code from the maximum likelihood exercise.\n",
    "    \n",
    "    # TODO: Repeat the above process--for each distance beyond 1, evaluate the words that\n",
    "    # might come after each word, and combine them weighting by relative probability\n",
    "    # into an estimate of what might appear next.\n",
    "    \n",
    "    return {}\n",
    "    \n",
    "print LaterWords(sample_memo,\"ahead\",2)"
   ]
  }
 ],
 "metadata": {
  "hide_input": false,
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
